SRC=./src
LIBC=$(SRC)/libc
BUILD=./build
LDF=./ld/kernel.lds

CFLAGS+=-fno-builtin # 不需要 gcc 内置函数
CFLAGS+=-nostdinc # 不需要标准头文件
CFLAGS+=-fno-pic # 不需要位置无关的代码
CFLAGS+=-fno-pie # 不需要位置无关的可执行程序
CFLAGS+=-nostdlib # 不需要标准库
CFLAGS+=-fno-stack-protector # 不需要栈保护
CFLAGS+=-Wall # 开启所有警告
CFLAGS:=$(strip ${CFLAGS})

LDFLAGS+=-b elf64-x86-64 # 64位x86处理器
LDFLAGS+=-z muldefs # 允许重复定义
LDFLAGS:=$(strip ${LDFLAGS})

QEMU=qemu-system-x86_64
QFLAGS+=-m 512M # 虚拟内存大小为256M
QFLAGS+=-boot c
QFLAGS+=-drive file=$(BUILD)/master.img,format=raw,if=ide,index=0
QFLAGS+=-audiodev pa,id=hda
QFLAGS+=-machine pcspk-audiodev=hda
QFLAGS+=-rtc base=localtime
QFLAGS:=$(strip ${QFLAGS})

DEBUG=-g
INCLUDE+=-I./include
INCLUDE+=-I$(LIBC)/include
INCLUDE:=$(strip ${INCLUDE})
SRCS = $(shell find $(SRC) -name '*.c')
OBJS = $(SRCS:$(SRC)/%.c=$(BUILD)/%.o)

$(BUILD)/master.img: $(BUILD)/boot/boot.bin		\
 					$(BUILD)/boot/loader.bin	\
					$(BUILD)/system.bin			\
					$(BUILD)/system.map
	yes | bximage -q -func=create -hd=16 -imgmode=flat -sectsize=512 $@
	dd if=$(BUILD)/boot/boot.bin of=$@ bs=512 count=1 conv=notrunc
	dd if=$(BUILD)/boot/loader.bin of=$@ bs=512 count=4 seek=2 conv=notrunc
	test -n "$$(find $(BUILD)/system.bin -size -100k)"
	dd if=$(BUILD)/system.bin of=$@ bs=512 count=200 seek=10 conv=notrunc

$(BUILD)/system.bin: $(BUILD)/kernel.bin
	$(shell mkdir -p $(dir $@))
	@objcopy -O binary $< $@

$(BUILD)/system.map: $(BUILD)/kernel.bin
	$(shell mkdir -p $(dir $@))
	@nm $< | sort > $@

$(BUILD)/kernel.bin: $(BUILD)/kernel/head.o \
					$(BUILD)/kernel/sys/schedule.o \
					$(BUILD)/kernel/sys/handler.o \
					$(OBJS)
	$(shell mkdir -p $(dir $@))
	@ld $(LDFLAGS) -T $(LDF) $^ -o $@

$(BUILD)/%.o: $(SRC)/%.c
	$(shell mkdir -p $(dir $@))
	@gcc $(CFLAGS) $(DEBUG) $(INCLUDE) -O2 -c $< -o $@

$(BUILD)/kernel/%.o: $(SRC)/kernel/%.asm
	$(shell mkdir -p $(dir $@))
	@nasm $(DEBUG) -gdwarf -f elf64 $< -o $@

$(BUILD)/boot/%.bin: $(SRC)/boot/%.asm
	$(shell mkdir -p $(dir $@))
	@nasm $(DEBUG) -f bin $^ -o $@

test: $(BUILD)/system.bin

.PHONY: bochs
bochs: $(BUILD)/master.img
	bochs -qf $(SRC)/bochsrc

.PHONY: qemu
qemu: $(BUILD)/master.img 
	$(QEMU) $(QFLAGS)

.PHONY: qemug
qemug: $(BUILD)/master.img 
	$(QEMU) $(QFLAGS) -s -S

.PHONY: clean
clean:
	rm -rf $(BUILD)/

.PHONY: stat
stat:
	@find . -type f \( -name "*.h" -o -name "*.c" -o -name "*.asm" \) -exec wc -l {} +